package search;

import agents.AutomatonAgent;
import env.Action;
import env.Enviroment;
import env.Tile;
import java.util.LinkedList;
import java.util.List;

/*************************************************************
 * ************************************************************
 * NOTE: FOR NOW, g=depth always!!!
 * @author user
 *************************************************************
 *************************************************************/
public class Node {    
    static int counter = 0;
    int id;
    private Node parent;
    //private Action action; //what got me here?
    // FullState:
    private SearchState state;
    //private int depth;
    int g; //path cost FOR NOW, g=depth always!!!
    int h; //heuristic
    int f; //only for A*
    int h1;
    int dist_death;
    private boolean isGoal;

    //public Node(Node parent, Action action, int depth, int g, SearchState state) {
    public Node(Node parent, int g, SearchState state) {
        this.parent = parent;
        //this.depth = depth;
        this.g = g;
        this.state = state;

        this.id = counter++;

        h=Enviroment.heuristic.h(state);

        f = h + g;
        
        this.isGoal = !state.isAlive | state.getFlags().size()==0;
    //System.out.println(" + created " +this);
    }

    public void getActionPath(LinkedList<Action> plan) {
        String s = "";
        int j = 100;//depth;
        for (Node i = this; i.parent != null; i = i.parent) {
            s = j + ")\t" + i + " ->\n" + s;
            j--;
            plan.addFirst(i.getState().myState.getLastAction());
        }
    //System.out.println("node path:\n" +s);
    }

//    public int getDepth() {
//        return depth;
//    }
    public int getG() {
        return g;
    }

    public SearchState getState() {
        return this.state;
    }
 

    //returns 0 to 3 new nodes
    @SuppressWarnings("empty-statement")
    public List<Node> expand() {
        List<Node> ans = new LinkedList<Node>();

        if (!state.isAlive) {
            return ans; //no moves for the dead man...
        }
        for (Action move : Action.values()) {
            if (this.id == 56) {
                System.out.println("");
            }
            SearchState next = this.state.clone(move);
            if (next.capture) {
                ans.add(new Node(this, g + 1 - Enviroment.FLAG_REWARD, next));
            } else {
                ans.add(new Node(this, g + 1, next));
            }
        }
        return ans;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Node other = (Node) obj;
        if (this.state != other.state && (this.state == null || !this.state.equals(other.state))) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        return state.hashCode();
    }

    @Override
    public String toString() {
        //return "node #"+id+" after "+getState().myState.getLastAction()+" from #"+(parent==null?"":parent.id)+"\t h1="+h1+", dist_death="+dist_death+" g="+g+", h="+h+", f="+(g+h)+", \t"+state;
        return "node #" + id + " (after #" + (parent == null ? "" : parent.id) + ")\t h1=" + h1 + ", dist_death=" + dist_death + " g=" + g + ", h=" + h + ", f=" + (g + h) + ", \t" + state;
    }

    boolean isGoal() {
        return this.isGoal;
    }
}
